#pragma once
#include <iostream>
#include <unordered_map>
#include <memory>
#include "connection.hpp"
#include "Epoller.hpp"
const static int gnum = 128;
class Reactor
{
public:
    Reactor()
        : _epoller(std::make_unique<Epoller>()), _isrunning(false)
    {
    }
    ~Reactor()
    {
    }

    void AddConnection(int fd, uint32_t event, int type)
    {
        // 创建一个连接
        Connection *conn = new Connection(fd);
        conn->SetEvent(event);
        conn->SetType(type);
        conn->SetReactor(this);
        if (conn->Type() == ListenConnection)
        {
            conn->RegisterHander(_OnConnect, nullptr, nullptr);
        }
        if (conn->Type() == NormalConnection)
        {
            conn->RegisterHander(_OnRecver, _OnSender, _OnExcepter);
        }
        // 将连接放到内核中
        if (!_epoller->AddEvent(conn->Connectionfd(), conn->Event()))
            return;
        // 将连接托管给_connections
        _connections.insert(std::make_pair(fd, conn));
    }
    // 判断连接是否存在
    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }

    void SetOnConnect(hander_t OnConnect)
    {
        _OnConnect = OnConnect;
    }

    void SetOnNormalHandler(hander_t recver, hander_t sender, hander_t excepter)
    {
        _OnRecver = recver;
        _OnSender = sender;
        _OnExcepter = excepter;
    }

    void EnableConnectReadWrite(int fd, bool reader, bool writer)
    {
        if (!IsConnectionExists(fd))
            return;
        uint32_t ev = {(reader ? EPOLLIN : 0) | (writer ? EPOLLOUT : 0) | EPOLLET};
        _connections[fd]->SetEvent(ev);
    }
    bool DelConnection(int sockfd)
    {
        if (!IsConnectionExists(sockfd))
            return false;
        LOG(DEBUG, "connection del success!sockfd:%d\n", sockfd);
        // 删除内核关心
        _epoller->DelEvent(sockfd);
        // 关闭文件描述符
        close(sockfd);
        // 在_connections中删除
        delete _connections[sockfd];
        _connections.erase(sockfd);
        return true;
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(recvs, gnum, timeout);
        LOG(DEBUG, "epoll_wait success %d\n", n);
        for (int i = 0; i < n; i++)
        {
            int sockfd = recvs[i].data.fd;    // 就绪连接的fd
            uint32_t event = recvs[i].events; // 就绪连接关心的事件

            if (event & EPOLLHUP)
                event |= (EPOLLIN | EPOLLOUT);
            if (event & EPOLLERR)
                event |= (EPOLLIN | EPOLLOUT);

            if (event & EPOLLIN)
            {
                if (IsConnectionExists(sockfd) && _connections[sockfd]->_hander_recver)
                {
                    _connections[sockfd]->_hander_recver(_connections[sockfd]);
                }
            }
            if (event & EPOLLOUT)
            {
                if (IsConnectionExists(sockfd) && _connections[sockfd]->_hander_sender)
                {
                    _connections[sockfd]->_hander_sender(_connections[sockfd]);
                }
            }
        }
    }
    // 事件派发
    void Distach()
    {
        int timeout = -1;
        _isrunning = true;
        while (_isrunning)
        {
            LoopOnce(timeout);
        }
        _isrunning = false;
    }

private:
    std::unordered_map<int, Connection *> _connections; // key为fd value为Connection
    std::unique_ptr<Epoller> _epoller;
    struct epoll_event recvs[gnum];
    bool _isrunning;

    // 处理listen连接的函数
    hander_t _OnConnect;
    // 处理普通连接的函数集
    hander_t _OnRecver;
    hander_t _OnSender;
    hander_t _OnExcepter;
};